/**
 *
 * User: Zhikang.Peng
 * Date: 2018/04/24 15:13
 */
package constants

import (
	"gitee.com/thghh/jvmgo/instructions/base"
	"gitee.com/thghh/jvmgo/rtda"
	"gitee.com/thghh/jvmgo/rtda/heap"
)

// 将int, float或String型常量值从常量池中推送至栈顶
type LDC struct{ base.Index8Instruction }

func (self *LDC) Execute(frame *rtda.Frame) {
	_ldc(frame, self.Index)
}

// 将int, float或String型常量值从常量池中推送至栈顶（宽索引）
type LDC_W struct{ base.Index16Instruction }

func (self *LDC_W) Execute(frame *rtda.Frame) {
	_ldc(frame, self.Index)
}

func _ldc(frame *rtda.Frame, index uint) {
	stack := frame.OperandStack()
	class := frame.Method().Class()
	cp := frame.Method().Class().ConstantPool()
	c := cp.GetConstant(index)
	switch c.(type) {
	case int32:
		stack.PushInt(c.(int32))
	case float32:
		stack.PushFloat(c.(float32))
	case string:
		internedStr := heap.JString(class.ClassLoader(), c.(string))
		stack.PushReference(internedStr)
	case *heap.ClassRef:
		classRef := c.(*heap.ClassRef)
		classObj := classRef.ResolvedClass().Object()
		stack.PushReference(classObj)
		// case MethodType, MethodHandle
	default:
		panic("todo: ldc!")
	}
}

// 将long或double型常量值从常量池中推送至栈顶（宽索引）
type LDC2_W struct{ base.Index16Instruction }

func (self *LDC2_W) Execute(frame *rtda.Frame) {
	stack := frame.OperandStack()
	cp := frame.Method().Class().ConstantPool()
	c := cp.GetConstant(self.Index)
	switch c.(type) {
	case int64:
		stack.PushLong(c.(int64))
	case float64:
		stack.PushDouble(c.(float64))
	default:
		panic("java.lang.ClassFormatError")
	}
}
